package gee

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

const banner = `
 _ __ (_)_ __   __ _ 
| '_ \| | '_ \ / _" |
| |_) | | | | | (_| |
| .__/|_|_| |_|\__, |
|_|            |___/ v%s
High performance, minimalist Go web framework
`

const (
	version = "1.0.0"
)

type HandlerFunc func(c *Context)

type Engine struct {
	Router       *router `json:"router"`
	*RouterGroup `json:"router_group"`
	Groups       []*RouterGroup `json:"groups"`
}

type RouterGroup struct {
	Prefix      string        `json:"prefix"`
	Middlewares []HandlerFunc `json:"middlewares"`
	Engine      *Engine       `json:"engine"`
}

func New() *Engine {
	e := &Engine{
		Router: NewRouter(),
	}
	e.RouterGroup = &RouterGroup{Engine: e}
	e.Groups = []*RouterGroup{e.RouterGroup}
	return e
}

func (group *RouterGroup) Group(prefix string) *RouterGroup {
	e := group.Engine
	newGroup := &RouterGroup{
		Prefix: prefix,
		Engine: e,
	}
	e.Groups = append(e.Groups, newGroup)
	return newGroup
}

func (group *RouterGroup) addRoute(method, comp string, handler HandlerFunc) {
	patter := group.Prefix + comp
	log.Printf("Route %4s - %s", method, patter)
	group.Engine.Router.addRoute(method, patter, handler)
}

func (e *Engine) addRoute(method string, pattern string, handler HandlerFunc) {
	e.Router.addRoute(method, pattern, handler)
}

func (group *RouterGroup) GET(pattern string, handler HandlerFunc) {
	group.addRoute("GET", pattern, handler)
}

func (group *RouterGroup) POST(pattern string, handler HandlerFunc) {
	group.addRoute("POST", pattern, handler)
}

func (e *Engine) Run(addr string) error {
	fmt.Fprintf(os.Stdout, banner, version)
	return http.ListenAndServe(addr, e)
}

func (e *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := NewContext(w, req)
	e.Router.handle(c)
}
